package com.example.mapperapi.annotation;

import com.example.mapperapi.mapperMethod.DefaultMapperMethod;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.function.Function;

/**
 * 映射普通字段,Integer,Long,Double,String
 * 对基本类型(安全)互转
 *
 * value为映射的对应字段名
 * method为自定义方法,若定义则传递一个实现Function接口的实现类字节码,自定义方法优先级最大
 * precision为浮点型保留的小数位,默认为2,<=0则取整
 * force 为 是否强制转换，默认不做强制
 *
 * 转换规则:
 *        1. 任何类型 -> String      toString后直接赋值(无任何异常)
 *             "abc.13asd"  ->   "abc.13asd"
 *        2. 任何类型 -> Integer     任何类型转String再转Double,再与Integer最大值比较
 *              123         ->   123
 *              123.01      ->   123
 *             "123"        ->   123
 *             "123.01"     ->   123
 *             "1234as嗷嗷"  ->  打印错误信息,不转换
 *             12345678901  ->  不抱错,直接返回(原因：(超过integer最大值))
 *             "12345678901" -> 不抱错,直接返回(原因：(超过integer最大值))
 *        3. 任何类型  -> Double   通过BigDecimal转换,根据precision保留小数位
 *             123456789 -> 123456789.00
 *             123.123   -> 123.123
 *            "123.123"  -> 123.123
 *             1234567890123456789.123  -> 1.23456789012345677E18
 *             "sdasd"   -> 打印错误信息,不转换
 *        4. 任何类型  -> Long
 *             "123.123"  -> 123
 *             "123"      -> 123
 *             123        -> 123
 *             123.01     -> 123
 *             "adafa"    -> 打印错误信息,不转换
 *             "12345678901234567890123" -> 打印错误信息,不转换
 * 强制规则:
 * String1->String2时发生变化
 *
 *        1.String1是数字类型字符串,如:       "1234.123"  "123"   "123.0"
 *          则保留小数位生成String,如:        "1234.12"   "123"   "123.0"
 *
 *        2.String1即使超过了Long最大19位,double失去精准值的17位则通过截取字符串来生成String2,如下
 *          "1234567890123456789"       ->     "1234567890123456789.00"
 *          "1234567890123456789.12345" ->     "1234567890123456789.12"
 *          即:通过字符串的正则判断和截取实现完全精准值的保留小数位,precision为0则取整
 *
 *        3.String1不为数字类型字符串时 直接赋值给String2
 *
 *
 * @author 徐鑫
 * @date 2023/03/25
 */
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MapperField {
    String value();
    Class<? extends Function<Object,Object>> method() default DefaultMapperMethod.class;
    int precision() default 2;
    boolean force() default false;
}
